home *** CD-ROM | disk | FTP | other *** search
/ Internet Info 1994 March / Internet Info CD-ROM (Walnut Creek) (March 1994).iso / networking / ip / ka9q / src.arc / NRCMD.C < prev    next >
C/C++ Source or Header  |  1989-08-19  |  24KB  |  1,018 lines

  1. /* net/rom user command processing
  2.  * Copyright 1989 by Daniel M. Frank, W9NK.  Permission granted for
  3.  * non-commercial distribution only.
  4.  */
  5.  
  6. #include <stdio.h>
  7. #include <ctype.h>
  8. #include "global.h"
  9. #include "mbuf.h"
  10. #include "ax25.h"
  11. #include "ax_mbx.h"
  12. #include "netrom.h"
  13. #include "nr4.h"
  14. #include "timer.h"
  15. #include "iface.h"
  16. #include "lapb.h"
  17. #include "cmdparse.h"
  18. #include "session.h"
  19. #include "socket.h"
  20. #include "commands.h"
  21.  
  22. static int Nrsocket = -1;
  23. struct ax25_addr Nr4user;
  24.  
  25. char *Nr4states[] = {
  26.     "Disconnected",
  27.     "Conn Pending",
  28.     "Connected",
  29.     "Disc Pending",
  30.     "Listening"
  31. } ;
  32.  
  33. char *Nr4reasons[] = {
  34.     "Normal",
  35.     "By Peer",
  36.     "Timeout",
  37.     "Reset",
  38.     "Refused"
  39. } ;
  40. static int dobcnodes __ARGS((int argc,char *argv[],void *p));
  41. static int dointerface __ARGS((int argc,char *argv[],void *p));
  42. static int donfadd __ARGS((int argc,char *argv[],void *p));
  43. static int donfdrop __ARGS((int argc,char *argv[],void *p));
  44. static int donfdump __ARGS((void));
  45. static int donfmode __ARGS((int argc,char *argv[],void *p));
  46. static int donodefilter __ARGS((int argc,char *argv[],void *p));
  47. static void donodetick __ARGS((void));
  48. static int donodetimer __ARGS((int argc,char *argv[],void *p));
  49. static int donracktime __ARGS((int argc,char *argv[],void *p));
  50. static int donrchoketime __ARGS((int argc,char *argv[],void *p));
  51. static int donrconnect __ARGS((int argc,char *argv[],void *p));
  52. static int donrirtt __ARGS((int argc,char *argv[],void *p));
  53. static int donrkick __ARGS((int argc,char *argv[],void *p));
  54. static int dorouteadd __ARGS((int argc,char *argv[],void *p));
  55. static int doroutedrop __ARGS((int argc,char *argv[],void *p));
  56. static int doroutedump __ARGS((void));
  57. static int dorouteinfo __ARGS((int argc,char *argv[],void *p));
  58. static int donrqlimit __ARGS((int argc,char *argv[],void *p));
  59. static int donrreset __ARGS((int argc,char *argv[],void *p));
  60. static int donrretries __ARGS((int argc,char *argv[],void *p));
  61. static int donrroute __ARGS((int argc,char *argv[],void *p));
  62. static int donrstatus __ARGS((int argc,char *argv[],void *p));
  63. static int donrttl __ARGS((int argc,char *argv[],void *p));
  64. static int donruser __ARGS((int argc,char *argv[],void *p));
  65. static int donrverbose __ARGS((int argc,char *argv[],void *p));
  66. static int donrwindow __ARGS((int argc,char *argv[],void *p));
  67. static void doobsotick __ARGS((void));
  68. static int doobsotimer __ARGS((int argc,char *argv[],void *p));
  69. static int putalias __ARGS((char *to, char *from,int complain));
  70.  
  71. static struct cmds Nrcmds[] = {
  72.     "acktime",    donracktime,    0, 0,    NULLCHAR,
  73.     "bcnodes",    dobcnodes,    0, 2,    "netrom bcnodes <interface>",
  74.     "connect",    donrconnect, 1024, 2,    "netrom connect <node>",
  75.     "choketime",    donrchoketime,    0, 0,    NULLCHAR,
  76.     "interface",    dointerface,    0, 4,
  77.         "netrom interface <interface> <alias> <quality>",
  78.     "irtt",        donrirtt,    0, 0,    NULLCHAR,
  79.     "kick",        donrkick,    0, 2,    "netrom kick <&nrcb>",
  80.     "nodefilter",    donodefilter,    0, 0,    NULLCHAR,
  81.     "nodetimer",    donodetimer,    0, 0,    NULLCHAR,
  82.     "obsotimer",    doobsotimer,    0, 0,    NULLCHAR,
  83.     "qlimit",    donrqlimit,    0, 0,    NULLCHAR,
  84.     "reset",    donrreset,    0, 2,    "netrom reset <&nrcb>",
  85.     "retries",    donrretries,    0, 0,    NULLCHAR,
  86.     "route",    donrroute,    0, 0,    NULLCHAR,
  87.     "status",    donrstatus,    0, 0,    NULLCHAR,
  88.     "ttl",        donrttl,    0, 0,    NULLCHAR,
  89.     "user",        donruser,    0, 0,    NULLCHAR,
  90.     "verbose",    donrverbose,    0, 0,    NULLCHAR,
  91.     "window",    donrwindow,    0, 0,    NULLCHAR,
  92.     NULLCHAR,
  93. } ;
  94.  
  95. static struct timer Nodetimer ;    /* timer for nodes broadcasts */
  96. static struct timer Obsotimer ;    /* timer for aging routes */
  97.  
  98. /* Command multiplexer */
  99. int
  100. donetrom(argc,argv,p)
  101. int argc ;
  102. char *argv[] ;
  103. void *p;
  104. {
  105.     return subcmd(Nrcmds,argc,argv,p) ;
  106. }
  107.  
  108. static struct cmds Routecmds[] = {
  109.     "add",    dorouteadd,    0, 6,
  110.         "netrom route add <alias> <destination> <interface> <quality> <neighbor>",
  111.     "drop",    doroutedrop, 0, 4,
  112.         "netrom route drop <destination> <neighbor> <interface>",
  113.     "info", dorouteinfo, 0, 2,
  114.         "netrom route info <destination>",
  115.     NULLCHAR,
  116. } ;
  117.  
  118. /* Route command multiplexer */
  119. static int
  120. donrroute(argc, argv,p)
  121. int argc ;
  122. char *argv[] ;
  123. void *p;
  124. {
  125.     if (argc < 2) {
  126.         doroutedump() ;
  127.         return 0 ;
  128.     }
  129.     return subcmd(Routecmds,argc,argv,p) ;
  130. }
  131.  
  132. /* Dump a list of known routes */
  133. static int
  134. doroutedump()
  135. {
  136.     register struct nrroute_tab *rp ;
  137.     register int i, column ;
  138.     char buf[16] ;
  139.     char *cp ;
  140.     
  141.     column = 1 ;
  142.     
  143.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  144.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rp->next) {
  145.             strcpy(buf,rp->alias) ;
  146.             /* remove trailing spaces */
  147.             if ((cp = strchr(buf,' ')) == NULLCHAR)
  148.                 cp = &buf[strlen(buf)] ;
  149.             if (cp != buf)        /* don't include colon for null alias */
  150.                 *cp++ = ':' ;
  151.             pax25(cp,&rp->call) ;
  152.             printf("%-16s  ",buf) ;
  153.             if (column++ == 4) {
  154.                 printf("\n") ;
  155.                 column = 1 ;
  156.             }
  157.         }
  158.  
  159.     if (column != 1)
  160.         printf("\n") ;
  161.         
  162.     return 0 ;
  163. }
  164.  
  165. /* print detailed information on an individual route */
  166. static int
  167. dorouteinfo(argc,argv,p)
  168. int argc ;
  169. char *argv[] ;
  170. void *p;
  171. {
  172.     register struct nrroute_tab *rp ;
  173.     register struct nr_bind *bp ;
  174.     register struct nrnbr_tab *np ;
  175.     struct ax25_addr dest ;
  176.     char neighbor[60] ;
  177.  
  178.     if (setcall(&dest,argv[1]) == -1) {
  179.         printf ("bad destination name\n") ;
  180.         return -1 ;
  181.     }
  182.         
  183.     if ((rp = find_nrroute(&dest)) == NULLNRRTAB) {
  184.         printf("no such route\n") ;
  185.         return -1 ;
  186.     }
  187.  
  188.     for (bp = rp->routes ; bp != NULLNRBIND ; bp = bp->next) {
  189.         np = bp->via ;
  190.         psax25(neighbor,np->call) ;
  191.         printf("%1s %3d  %3d  %-8s  %s\n",
  192.                 (bp->flags & NRB_PERMANENT ? "P" :
  193.                  bp->flags & NRB_RECORDED ? "R" : " "),
  194.                 bp->quality,bp->obsocnt,
  195.                 Nrifaces[np->iface].iface->name,
  196.                 neighbor) ;
  197.     }
  198.     return 0 ;
  199. }
  200.         
  201. /* convert a null-terminated alias name to a blank-filled, upcased */
  202. /* version.  Return -1 on failure. */
  203. static int
  204. putalias(to,from,complain)
  205. register char *to, *from ;
  206. int complain ;    
  207. {
  208.     int len, i ;
  209.     
  210.     if ((len = strlen(from)) > ALEN) {
  211.         if (complain)
  212.             printf ("alias too long - six characters max\n") ;
  213.         return -1 ;
  214.     }
  215.     
  216.     for (i = 0 ; i < ALEN ; i++) {
  217.         if (i < len) {
  218.             if (islower(*from))
  219.                 *to++ = toupper(*from++) ;
  220.             else
  221.                 *to++ = *from++ ;
  222.         }
  223.         else
  224.             *to++ = ' ' ;
  225.     }
  226.             
  227.     *to = '\0' ;
  228.     return 0 ;
  229. }
  230.  
  231. /* Add a route */
  232. static int
  233. dorouteadd(argc, argv,p)
  234. int argc ;
  235. char *argv[] ;
  236. void *p;
  237. {
  238.     char alias[7] ;
  239.     struct ax25_addr dest ;
  240.     unsigned quality ;
  241.     char neighbor[AXALEN * 3] ;
  242.     register int i ;
  243.     int naddr ;
  244.  
  245.     /* format alias (putalias prints error message if necessary) */
  246.     if (putalias(alias,argv[1],1) == -1)
  247.         return -1 ;
  248.  
  249.     /* format destination callsign */
  250.     if (setcall(&dest,argv[2]) == -1) {
  251.         printf("bad destination callsign\n") ;
  252.         return -1 ;
  253.     }
  254.  
  255.     /* find interface */
  256.     for (i = 0 ; i < Nr_numiface ; i++)
  257.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  258.             break ;
  259.     if (i == Nr_numiface) {
  260.         printf("Interface \"%s\" not found\n",argv[3]) ;
  261.         return -1 ;
  262.     }
  263.     
  264.     /* get and check quality value */
  265.     if ((quality = atoi(argv[4])) > 255) {
  266.         printf("maximum route quality is 255\n") ;
  267.         return -1 ;
  268.     }
  269.  
  270.     /* Change from 871225 -- no digis in net/rom table */
  271.     naddr = argc - 5 ;
  272.     if (naddr > 1) {
  273.         printf("Use the ax25 route command to specify digipeaters\n") ;
  274.         return -1 ;
  275.     }
  276.     
  277.     /* format neighbor address string */
  278.     setpath(neighbor,argv[5]) ;
  279.  
  280.     return nr_routeadd(alias,&dest,i,quality,neighbor,1,0) ;
  281. }
  282.  
  283.  
  284. /* drop a route */
  285. static int
  286. doroutedrop(argc,argv,p)
  287. int argc ;
  288. char *argv[] ;
  289. void *p;
  290. {
  291.     struct ax25_addr dest, neighbor ;
  292.     register int i ;
  293.  
  294.     /* format destination and neighbor callsigns */
  295.     if (setcall(&dest,argv[1]) == -1) {
  296.         printf("bad destination callsign\n") ;
  297.         return -1 ;
  298.     }
  299.     if (setcall(&neighbor,argv[2]) == -1) {
  300.         printf("bad neighbor callsign\n") ;
  301.         return -1 ;
  302.     }
  303.  
  304.     /* find interface */
  305.     for (i = 0 ; i < Nr_numiface ; i++)
  306.         if (!strcmp(Nrifaces[i].iface->name,argv[3]))
  307.             break ;
  308.     if (i == Nr_numiface) {
  309.         printf("Interface \"%s\" not found\n",argv[3]) ;
  310.         return -1 ;
  311.     }
  312.  
  313.     return nr_routedrop(&dest,&neighbor,i) ;
  314. }
  315.     
  316.     
  317. /* make an interface available to net/rom */
  318. static int
  319. dointerface(argc,argv,p)
  320. int argc ;
  321. char *argv[] ;
  322. void *p;
  323. {
  324.     int i ;
  325.     register struct iface *ifp ;
  326.  
  327.     if (Nr_iface == NULLIF) {
  328.         printf("Attach netrom interface first\n") ;
  329.         return 1 ;
  330.     }
  331.     
  332.     if (Nr_numiface >= NRNUMIFACE) {
  333.         printf("Only %d net/rom interfaces available\n",NRNUMIFACE) ;
  334.         return 1 ;
  335.     }
  336.     
  337.     for(ifp=Ifaces;ifp != NULLIF;ifp = ifp->next){
  338.         if(strcmp(argv[1],ifp->name) == 0)
  339.             break;
  340.     }
  341.     if(ifp == NULLIF){
  342.         printf("Interface \"%s\" unknown\n",argv[1]);
  343.         return 1;
  344.     }
  345.     for (i = 0 ; i < Nr_numiface ; i++)
  346.         if (Nrifaces[i].iface == ifp) {
  347.             printf("Interface \"%s\" is already registered\n",argv[1]) ;
  348.             return 1 ;
  349.         }
  350.         
  351.     Nrifaces[Nr_numiface].iface = ifp ;
  352.  
  353.     if (putalias(Nrifaces[Nr_numiface].alias,argv[2],1) == -1)
  354.         return 1 ;
  355.         
  356.     if ((Nrifaces[Nr_numiface].quality = atoi(argv[3])) > 255) {
  357.         printf("Quality cannot be greater than 255\n") ;
  358.         return 1 ;
  359.     }
  360.         
  361.     Nr_numiface++ ;            /* accept this interface */
  362.     return 0 ;
  363. }
  364.  
  365. /* Broadcast nodes list on named interface. */
  366. static int
  367. dobcnodes(argc,argv,p)
  368. int argc ;
  369. char *argv[] ;
  370. void *p;
  371. {
  372.     register int i ;
  373.  
  374.     for (i = 0 ; i < Nr_numiface ; i++)
  375.         if (!strcmp(Nrifaces[i].iface->name,argv[1]))
  376.             break ;
  377.     if (i == Nr_numiface) {
  378.         printf("Interface \"%s\" not found\n",argv[1]) ;
  379.         return 1 ;
  380.     }
  381.         
  382.     nr_bcnodes(i) ;
  383.     return 0;
  384. }
  385.  
  386. #define TICKSPERSEC    (1000L / MSPTICK)    /* Ticks per second */
  387.  
  388. /* Set outbound node broadcast interval */
  389. static int
  390. donodetimer(argc,argv,p)
  391. int argc;
  392. char *argv[];
  393. void *p;
  394. {
  395.     if(argc < 2){
  396.         printf("Nodetimer %lu/%lu seconds\n",(Nodetimer.start - Nodetimer.count)/TICKSPERSEC,
  397.         Nodetimer.start/TICKSPERSEC);
  398.         return 0;
  399.     }
  400.     stop_timer(&Nodetimer) ;    /* in case it's already running */
  401.     Nodetimer.func = (void (*)())donodetick;/* what to call on timeout */
  402.     Nodetimer.arg = NULLCHAR;        /* dummy value */
  403.     Nodetimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  404.     start_timer(&Nodetimer);        /* and fire it up */
  405.     return 0;
  406. }
  407.  
  408. static void
  409. donodetick()
  410. {
  411.     register int i ;
  412.  
  413.     for (i = 0 ; i < Nr_numiface ; i++)
  414.         nr_bcnodes(i) ;
  415.  
  416.     /* Restart timer */
  417.     start_timer(&Nodetimer) ;
  418. }
  419.  
  420. /* Set timer for aging routes */
  421. static int
  422. doobsotimer(argc,argv,p)
  423. int argc;
  424. char *argv[];
  425. void *p;
  426. {
  427.     if(argc < 2){
  428.         printf("Obsotimer %lu/%lu seconds\n",(Obsotimer.start - Obsotimer.count)/TICKSPERSEC,
  429.         Obsotimer.start/TICKSPERSEC);
  430.         return 0;
  431.     }
  432.     stop_timer(&Obsotimer) ;    /* just in case it's already running */
  433.     Obsotimer.func = (void (*)())doobsotick;/* what to call on timeout */
  434.     Obsotimer.arg = NULLCHAR;        /* dummy value */
  435.     Obsotimer.start = atoi(argv[1])*TICKSPERSEC;    /* set timer duration */
  436.     start_timer(&Obsotimer);        /* and fire it up */
  437.     return 0;
  438. }
  439.  
  440.  
  441. /* Go through the routing table, reducing the obsolescence count of
  442.  * non-permanent routes, and purging them if the count reaches 0
  443.  */
  444. static void
  445. doobsotick()
  446. {
  447.     register struct nrnbr_tab *np ;
  448.     register struct nrroute_tab *rp, *rpnext ;
  449.     register struct nr_bind *bp, *bpnext ;
  450.     struct ax25_addr neighbor ;
  451.     int i ;
  452.  
  453.     for (i = 0 ; i < NRNUMCHAINS ; i++) {
  454.         for (rp = Nrroute_tab[i] ; rp != NULLNRRTAB ; rp = rpnext) {
  455.             rpnext = rp->next ;     /* save in case we free this route */
  456.             for (bp = rp->routes ; bp != NULLNRBIND ; bp = bpnext) {
  457.                 bpnext = bp->next ;    /* in case we free this binding */
  458.                 if (bp->flags & NRB_PERMANENT)    /* don't age these */
  459.                     continue ;
  460.                 if (--bp->obsocnt == 0) {        /* time's up! */
  461.                     if (bp->next != NULLNRBIND)
  462.                         bp->next->prev = bp->prev ;
  463.                     if (bp->prev != NULLNRBIND)
  464.                         bp->prev->next = bp->next ;
  465.                     else
  466.                         rp->routes = bp->next ;
  467.                     rp->num_routes-- ;            /* one less binding */
  468.                     np = bp->via ;                /* find the neighbor */
  469.                     free(bp) ;                /* now we can free the bind */
  470.                     /* Check to see if we can free the neighbor */
  471.                     if (--np->refcnt == 0) {
  472.                         if (np->next != NULLNTAB)
  473.                             np->next->prev = np->prev ;
  474.                         if (np->prev != NULLNTAB)
  475.                             np->prev->next = np->next ;
  476.                         else {
  477.                             memcpy(neighbor.call,np->call,ALEN) ;
  478.                             neighbor.ssid = np->call[ALEN] ;
  479.                             Nrnbr_tab[nrhash(&neighbor)] = np->next ;
  480.                         }
  481.                         free(np) ;    /* free the storage */
  482.                     }
  483.                 }
  484.             }
  485.             if (rp->num_routes == 0) {        /* did we free them all? */
  486.                 if (rp->next != NULLNRRTAB)
  487.                     rp->next->prev = rp->prev ;
  488.                 if (rp->prev != NULLNRRTAB)
  489.                     rp->prev->next = rp->next ;
  490.                 else
  491.                     Nrroute_tab[i] = rp->next ;
  492.  
  493.                 free(rp) ;
  494.             }
  495.         }
  496.     }
  497.  
  498.     start_timer(&Obsotimer) ;
  499. }
  500.  
  501.  
  502. static struct cmds Nfcmds[] = {
  503.     "add",    donfadd,    0, 3,
  504.         "netrom nodefilter add <neighbor> <interface>",
  505.     "drop",    donfdrop,    0, 3,
  506.         "netrom nodefilter drop <neighbor> <interface>",
  507.     "mode",    donfmode,    0, 0,    NULLCHAR,
  508.     NULLCHAR,    NULLFP,    0, 0,
  509.         "nodefilter subcommands: add drop mode",
  510. } ;
  511.  
  512. /* nodefilter command multiplexer */
  513. static int
  514. donodefilter(argc,argv,p)
  515. int argc ;
  516. char *argv[] ;
  517. void *p;
  518. {
  519.     if (argc < 2) {
  520.         donfdump() ;
  521.         return 0 ;
  522.     }
  523.     return subcmd(Nfcmds,argc,argv,p) ;
  524. }
  525.  
  526. /* display a list of <callsign,interface> pairs from the filter
  527.  * list.
  528.  */
  529. static int
  530. donfdump()
  531. {
  532.     int i, column = 1 ;
  533.     struct nrnf_tab *fp ;
  534.     char buf[16] ;
  535.  
  536.     for (i = 0 ; i < NRNUMCHAINS ; i++)
  537.         for (fp = Nrnf_tab[i] ; fp != NULLNRNFTAB ; fp = fp->next) {
  538.             pax25(buf,&fp->neighbor) ;
  539.             printf("%-7s %-8s  ",
  540.                     buf,Nrifaces[fp->iface].iface->name) ;
  541.             if (column++ == 4) {
  542.                 printf("\n") ;
  543.                 column = 1 ;
  544.             }
  545.         }
  546.  
  547.     if (column != 1)
  548.         printf("\n") ;
  549.  
  550.     return 0 ;
  551. }
  552.  
  553. /* add an entry to the filter table */
  554. static int
  555. donfadd(argc,argv,p)
  556. int argc ;
  557. char *argv[] ;
  558. void *p;
  559. {
  560.     struct ax25_addr neighbor ;
  561.     register int i ;
  562.  
  563.     /* format callsign */
  564.     if (setcall(&neighbor,argv[1]) == -1) {
  565.         printf("bad neighbor callsign\n") ;
  566.         return -1 ;
  567.     }
  568.  
  569.     /* find interface */
  570.     for (i = 0 ; i < Nr_numiface ; i++)
  571.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  572.             break ;
  573.     if (i == Nr_numiface) {
  574.         printf("Interface \"%s\" not found\n",argv[2]) ;
  575.         return -1 ;
  576.     }
  577.  
  578.     return nr_nfadd(&neighbor,i) ;
  579. }
  580.  
  581. /* drop an entry from the filter table */
  582. static int
  583. donfdrop(argc,argv,p)
  584. int argc ;
  585. char *argv[] ;
  586. void *p;
  587. {
  588.     struct ax25_addr neighbor ;
  589.     register int i ;
  590.  
  591.     /* format neighbor callsign */
  592.     if (setcall(&neighbor,argv[1]) == -1) {
  593.         printf("bad neighbor callsign\n") ;
  594.         return -1 ;
  595.     }
  596.  
  597.     /* find interface */
  598.     for (i = 0 ; i < Nr_numiface ; i++)
  599.         if (!strcmp(Nrifaces[i].iface->name,argv[2]))
  600.             break ;
  601.     if (i == Nr_numiface) {
  602.         printf("Interface \"%s\" not found\n",argv[2]) ;
  603.         return -1 ;
  604.     }
  605.  
  606.     return nr_nfdrop(&neighbor,i) ;
  607. }
  608.  
  609. /* nodefilter mode subcommand */
  610. static int
  611. donfmode(argc,argv,p)
  612. int argc ;
  613. char *argv[] ;
  614. void *p;
  615. {
  616.     if (argc < 2) {
  617.         printf("filter mode is ") ;
  618.         switch (Nr_nfmode) {
  619.             case NRNF_NOFILTER:
  620.                 printf("none\n") ;
  621.                 break ;
  622.             case NRNF_ACCEPT:
  623.                 printf("accept\n") ;
  624.                 break ;
  625.             case NRNF_REJECT:
  626.                 printf("reject\n") ;
  627.                 break ;
  628.             default:
  629.                 printf("some strange, unknown value\n") ;
  630.         }
  631.         return 0 ;
  632.     }
  633.     
  634.     switch (argv[1][0]) {
  635.         case 'n':
  636.         case 'N':
  637.             Nr_nfmode = NRNF_NOFILTER ;
  638.             break ;
  639.         case 'a':
  640.         case 'A':
  641.             Nr_nfmode = NRNF_ACCEPT ;
  642.             break ;
  643.         case 'r':
  644.         case 'R':
  645.             Nr_nfmode = NRNF_REJECT ;
  646.             break ;
  647.         default:
  648.             printf("modes are: none accept reject\n") ;
  649.             return -1 ;
  650.     }
  651.  
  652.     return 0 ;
  653. }
  654.  
  655. /* netrom network packet time-to-live initializer */
  656. static int
  657. donrttl(argc, argv,p)
  658. int argc ;
  659. char *argv[] ;
  660. void *p;
  661. {
  662.     return setshort(&Nr_ttl,"Time to live",argc,argv);
  663. }
  664.  
  665. /* verbose route broadcast */
  666. static int
  667. donrverbose(argc,argv,p)
  668. int argc ;
  669. char *argv[] ;
  670. void *p;
  671. {
  672.     return setbool(&Nr_verbose,"Verbose flag",argc,argv);
  673. }
  674.  
  675. /* Initiate a NET/ROM transport connection */
  676. static int
  677. donrconnect(argc,argv,p)
  678. int argc ;
  679. char *argv[] ;
  680. void *p;
  681. {
  682.     struct ax25_addr *np ;
  683.     struct sockaddr_nr lsocket, fsocket;
  684.     char alias[10];
  685.     struct session *sp;
  686.  
  687.     /* Get a session descriptor */
  688.     if ((sp = newsession(argv[1],NRSESSION)) == NULLSESSION) {
  689.         printf("Too many sessions\n") ;
  690.         freeargs(argc,argv);
  691.         return 1 ;
  692.     }
  693.  
  694.     if((sp->s = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1){
  695.         freesession(sp);
  696.         printf("Can't create socket\n");
  697.         freeargs(argc,argv);
  698.         return 1;
  699.     }
  700.     lsocket.nr_family = AF_NETROM;
  701.     /* Set up our local username, bind would use Mycall instead */
  702.     memcpy(lsocket.nr_addr.user_call,&Nr4user,AXALEN);
  703.     /* Putting anything else than Mycall here will not work */
  704.     memcpy(lsocket.nr_addr.node_call,&Mycall,AXALEN);
  705.     bind(sp->s,(char *)&lsocket,sizeof(struct sockaddr_nr));
  706.  
  707.     /* See if the requested destination could be an alias, and */
  708.     /* find and use it if it is.  Otherwise assume it is an ax.25 */
  709.     /* address. */
  710.     
  711.     if (putalias(alias,argv[1],0) != -1 &&
  712.         (np = find_nralias(alias)) != NULLAXADDR) {
  713.         memcpy(fsocket.nr_addr.user_call,np,AXALEN) ;
  714.         memcpy(fsocket.nr_addr.node_call,np,AXALEN) ;
  715.     }
  716.     else {    /* parse ax25 callsign */
  717.         /* Only the user callsign of the remote station is never used by */
  718.         /* NET/ROM, but it is needed for the psocket() call. */
  719.         setcall((struct ax25_addr *)fsocket.nr_addr.user_call,argv[1]);
  720.         setcall((struct ax25_addr *)fsocket.nr_addr.node_call,argv[1]);
  721.     }
  722.     freeargs(argc,argv);
  723.     fsocket.nr_family = AF_NETROM;
  724.     pax25(alias,(struct ax25_addr *)fsocket.nr_addr.node_call);
  725.     printf("Trying %s...\n",alias);
  726.     return axnrconnect(sp, (char *)&fsocket, sizeof(struct sockaddr_nr));
  727. }
  728.  
  729. int
  730. nr4start(argc,argv,p)
  731. int argc;
  732. char *argv[];
  733. void *p;
  734. {
  735.     int s;
  736.  
  737.     freeargs(argc,argv);
  738.     if (Nrsocket != -1)
  739.         return -1;
  740.  
  741.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  742.     chname(Curproc,"NETROM listener");
  743.     Nrsocket = socket(AF_NETROM,SOCK_SEQPACKET,0);
  744.     /* bind() is done automatically */
  745.     if (listen(Nrsocket,1) == -1) {
  746.         close_s(Nrsocket);
  747.         Nrsocket = -1;
  748.         return -1;
  749.     }
  750.     for(;;){
  751.         if((s = accept(Nrsocket,NULLCHAR,NULLINT)) == -1)
  752.             break;    /* Service is shutting down */
  753.  
  754.         if (Ax25mbox)
  755.             newproc("mbox",2048,mbx_incom,s,(void *)NRSESSION,NULL);
  756.         else
  757.             newproc("in_ax25",2048,axnrhandle,s,(void *)NRSESSION,NULL);
  758.     }
  759.     close_s(Nrsocket);
  760.     Nrsocket = -1;
  761.     return 0;
  762. }
  763. int
  764. nr40(argc,argv,p)
  765. int argc;
  766. char *argv[];
  767. void *p;
  768. {
  769.     close_s(Nrsocket);
  770.     Nrsocket = -1;
  771.     return 0;
  772. }
  773.  
  774. /* Reset a net/rom connection abruptly */
  775. static int
  776. donrreset(argc,argv,p)
  777. int argc;
  778. char *argv[];
  779. void *p;
  780. {
  781.     struct nr4cb *cb ;
  782.     extern char Notval[];
  783.  
  784.     cb = (struct nr4cb *)htol(argv[1]);
  785.     if(!nr4valcb(cb)){
  786.         printf(Notval);
  787.         return 1;
  788.     }
  789.     reset_nr4(cb);
  790.     return 0;
  791. }
  792.  
  793. /* Force retransmission on a net/rom connection */
  794.  
  795. static int
  796. donrkick(argc,argv,p)
  797. int argc;
  798. char *argv[];
  799. void *p;
  800. {
  801.     struct nr4cb *cb ;
  802.     extern char Notval[];
  803.  
  804.     cb = (struct nr4cb *)htol(argv[1]);
  805.  
  806.     if (kick_nr4(cb) == -1) {
  807.         printf(Notval);
  808.         return 1;
  809.     } else
  810.         return 0;
  811. }
  812.  
  813. /* netrom transport ACK delay timer */
  814. static int
  815. donracktime(argc, argv,p)
  816. int argc ;
  817. char *argv[] ;
  818. void *p;
  819. {
  820.     return setlong(&Nr4acktime,"Ack delay time (ms)",argc,argv);
  821. }
  822.  
  823. /* netrom transport choke timeout */
  824. static int
  825. donrchoketime(argc, argv,p)
  826. int argc ;
  827. char *argv[] ;
  828. void *p;
  829. {
  830.     return setlong(&Nr4choketime,"Choke timeout (ms)",argc,argv);
  831. }
  832.  
  833. /* netrom transport initial round trip time */
  834.  
  835. static int
  836. donrirtt(argc, argv,p)
  837. int argc ;
  838. char *argv[] ;
  839. void *p;
  840. {
  841.     return setlong(&Nr4irtt,"Initial RTT (ms)",argc,argv);
  842. }
  843.  
  844. /* netrom transport receive queue length limit.  This is the */
  845. /* threshhold at which we will CHOKE the sender. */
  846.  
  847. static int
  848. donrqlimit(argc, argv,p)
  849. int argc ;
  850. char *argv[] ;
  851. void *p;
  852. {
  853.     return setshort(&Nr4qlimit,"Queue limit (bytes)",argc,argv);
  854. }
  855.  
  856. /* Display or change our NET/ROM username */
  857. static int
  858. donruser(argc,argv,p)
  859. int argc;
  860. char *argv[];
  861. void *p;
  862. {
  863.     char buf[15];
  864.  
  865.     if(argc < 2){
  866.         pax25(buf,&Nr4user);
  867.         printf("%s\n",buf);
  868.         return 0;
  869.     }
  870.     if(setcall(&Nr4user,argv[1]) == -1)
  871.         return -1;
  872.     Nr4user.ssid |= E;
  873.     return 0;
  874. }
  875.  
  876. /* netrom transport maximum window.  This is the largest send and */
  877. /* receive window we may negotiate */
  878.  
  879. static int
  880. donrwindow(argc, argv,p)
  881. int argc ;
  882. char *argv[] ;
  883. void *p;
  884. {
  885.     return setshort(&Nr4window,"Window (frames)",argc,argv);
  886. }
  887.  
  888. /* netrom transport maximum retries.  This is used in connect and */
  889. /* disconnect attempts; I haven't decided what to do about actual */
  890. /* data retries yet. */
  891.  
  892. static int
  893. donrretries(argc, argv,p)
  894. int argc ;
  895. char *argv[] ;
  896. void *p;
  897. {
  898.     return setshort(&Nr4retries,"Retry limit",argc,argv);
  899. }
  900.  
  901. /* Display the status of NET/ROM connections */
  902.  
  903. static int
  904. donrstatus(argc, argv,p)
  905. int argc ;
  906. char *argv[] ;
  907. void *p;
  908. {
  909.     int i ;
  910.     struct nr4cb *cb ;
  911.     char luser[10], ruser[10], node[10] ;
  912.     extern char Notval[] ;
  913.     
  914.     if (argc < 2) {
  915.         printf("     &CB Snd-W Snd-Q Rcv-Q     LUser      RUser @Node     State\n");
  916.         for (i = 0 ; i < NR4MAXCIRC ; i++) {
  917.             if ((cb = Nr4circuits[i].ccb) == NULLNR4CB)
  918.                 continue ;
  919.             pax25(luser,(struct ax25_addr *)cb->local.user_call) ;
  920.             pax25(ruser,(struct ax25_addr *)cb->remote.user_call) ;
  921.             pax25(node,(struct ax25_addr *)cb->remote.node_call) ;
  922.             printf("%8lx   %3d %5d %5d %9s  %9s %-9s %s\n",
  923.                    ptol(cb), cb->nbuffered, len_q(cb->txq),
  924.                    len_mbuf(cb->rxq), luser, ruser, node,
  925.                    Nr4states[cb->state]) ;
  926.         }
  927.         return 0 ;
  928.     }
  929.  
  930.     cb = (struct nr4cb *)htol(argv[1]) ;
  931.     if (!nr4valcb(cb)) {
  932.         printf(Notval) ;
  933.         return 1 ;
  934.     }
  935.  
  936.     donrdump(cb) ;
  937.     return 0 ;
  938. }
  939.  
  940. /* Dump one control block */
  941.  
  942. void
  943. donrdump(cb)
  944. struct nr4cb *cb ;
  945. {
  946.     char luser[10], ruser[10], node[10] ;
  947.     unsigned seq ;
  948.     struct nr4txbuf *b ;
  949.     struct timer *t ;
  950.  
  951.     pax25(luser,(struct ax25_addr *)cb->local.user_call) ;
  952.     pax25(ruser,(struct ax25_addr *)cb->remote.user_call) ;
  953.     pax25(node,(struct ax25_addr *)cb->remote.node_call) ;
  954.  
  955.     printf("Local: %s %d/%d Remote: %s @ %s %d/%d State: %s\n",
  956.            luser, cb->mynum, cb->myid, ruser, node,
  957.            cb->yournum, cb->yourid, Nr4states[cb->state]) ;
  958.  
  959.     printf("Window: %-5u Rxpect: %-5u RxNext: %-5u RxQ: %-5d %s\n",
  960.            cb->window, uchar(cb->rxpected), uchar(cb->rxpastwin),
  961.            len_mbuf(cb->rxq), cb->qfull ? "RxCHOKED" : "") ;
  962.  
  963.     printf(" Unack: %-5u Txpect: %-5u TxNext: %-5u TxQ: %-5d %s\n",
  964.            cb->nbuffered, uchar(cb->ackxpected), uchar(cb->nextosend),
  965.            len_q(cb->txq), cb->choked ? "TxCHOKED" : "") ;
  966.  
  967.     printf("TACK: ") ;
  968.     if (run_timer(&cb->tack))
  969.         printf("%lu", (cb->tack.start - cb->tack.count) * MSPTICK) ;
  970.     else
  971.         printf("stop") ;
  972.     printf("/%lu ms; ", cb->tack.start * MSPTICK) ;
  973.  
  974.     printf("TChoke: ") ;
  975.     if (run_timer(&cb->tchoke))
  976.         printf("%lu", (cb->tchoke.start - cb->tchoke.count) * MSPTICK) ;
  977.     else
  978.         printf("stop") ;
  979.     printf("/%lu ms; ", cb->tchoke.start * MSPTICK) ;
  980.  
  981.     printf("TCD: ") ;
  982.     if (run_timer(&cb->tcd))
  983.         printf("%lu", (cb->tcd.start - cb->tcd.count) * MSPTICK) ;
  984.     else
  985.         printf("stop") ;
  986.     printf("/%lu ms", cb->tcd.start * MSPTICK) ;
  987.  
  988.     if (run_timer(&cb->tcd))
  989.         printf("; Tries: %u\n", cb->cdtries) ;
  990.     else
  991.         printf("\n") ;
  992.  
  993.     printf("Backoff Level %u SRTT %ld ms Mean dev %ld ms\n",
  994.            cb->blevel, cb->srtt, cb->mdev) ;
  995.  
  996.     /* If we are connected and the send window is open, display */
  997.     /* the status of all the buffers and their timers */
  998.     
  999.     if (cb->state == NR4STCON && cb->nextosend != cb->ackxpected) {
  1000.  
  1001.         printf("TxBuffers:  Seq  Size  Tries  Timer\n") ;
  1002.  
  1003.         for (seq = cb->ackxpected ;
  1004.              nr4between(cb->ackxpected, seq, cb->nextosend) ;
  1005.              seq = (seq + 1) & NR4SEQMASK) {
  1006.  
  1007.             b = &cb->txbufs[seq % cb->window] ;
  1008.             t = &b->tretry ;
  1009.  
  1010.             printf("            %3u   %3d  %5d  %lu/%lu\n",
  1011.                    seq, len_mbuf(b->data), b->retries + 1,
  1012.                    (t->start - t->count) * MSPTICK, t->start * MSPTICK) ;
  1013.         }
  1014.  
  1015.     }
  1016.  
  1017. }
  1018.